package hu.bme.mit.obp.seammodel.ui;

import hu.bme.mit.inf.seample.gen.SeamApplicationSkeletonChecker;
import hu.bme.mit.inf.seample.gen.SeamApplicationSkeletonGenerator;
import hu.bme.mit.inf.seample.gen.SeamGenerationDescriptor;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.emf.mwe.core.issues.Issues;
import org.eclipse.emf.mwe.core.issues.MWEDiagnostic;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorActionDelegate;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;

import seample.GeneratorModel;

/**
 * Abstract base class for generator, validator actions.
 * @author Mark Czotter
 *
 */
public abstract class AbstractSeamApplicationSkeletonAction implements
		IObjectActionDelegate, IEditorActionDelegate {

	private GeneratorModel generatorModel;
	
	protected void doGenerateJob(final SeamGenerationDescriptor descriptor) {
		Job j = new Job("Generate Seam Application Skeleton") {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				System.out.println("Generate Seam Application Skeleton Started");
				IStatus status = Status.OK_STATUS;
				monitor.beginTask("Generate Seam Application Skeleton", 1000);
				try {
					System.out.println("Checking Seam Application Skeleton Started");
					SeamApplicationSkeletonChecker check = new SeamApplicationSkeletonChecker(descriptor);
					Issues i = check.check(monitor);
					if (i.getErrors().length > 0) {
						StringBuffer b = new StringBuffer();
						for (MWEDiagnostic m : i.getErrors()) {
							b.append(m.getMessage());
							b.append("\n");
						}
						status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, b.toString());
					} else {
						SeamApplicationSkeletonGenerator gen = new SeamApplicationSkeletonGenerator(descriptor);
						gen.generate(monitor);
					}
				} catch (OperationCanceledException e) {
					status = Status.CANCEL_STATUS;
				} catch (Exception e) {
					e.printStackTrace();
					status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.toString() + ": " +e.getMessage());
				} finally {
					monitor.done();
				}
				System.out.println("Generate Seam Application Skeleton Finished");
				return status;
			}
		};
		j.addJobChangeListener(new JobChangeAdapter() {
			@Override
			public void done(IJobChangeEvent event) {
				showDialog(event);
			}
		});
		j.setUser(true);
		j.schedule();
	}
	
	

	@Override
	public void selectionChanged(IAction action, ISelection selection) {
		if (selection instanceof IStructuredSelection) {
			if (((IStructuredSelection) selection).getFirstElement() instanceof GeneratorModel)
				generatorModel = (GeneratorModel) ((IStructuredSelection) selection).getFirstElement();
		}
	}

	@Override
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
	}
	
	@Override
	public void setActiveEditor(IAction action, IEditorPart targetEditor) {
	}
	
	/**
	 * Shows the proper dialog based on the actual IStatus.
	 * @param status
	 */
	protected void showDialog(final IJobChangeEvent event) {
		Display display = Display.getDefault();
		display.asyncExec(new Runnable() {
			@Override
			public void run() {
				Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
				switch (event.getResult().getSeverity()) {
				case IStatus.ERROR:
					ErrorDialog.openError(shell, "Code Generation Error", null, event.getResult());
					break;
				case IStatus.CANCEL:
					MessageDialog.openInformation(shell, "Code Generation Canceled", event.getJob().getName() + "Code generation canceled!");
					break;
				default:
					MessageDialog.openInformation(shell, "Code generation finished!", event.getJob().getName()+" finished without errors!");
					break;
				}
			}
			
		});
	}
	
	public GeneratorModel getGeneratorModel() {
		return generatorModel;
	}

}
